iT邦幫忙

2022 iThome 鐵人賽

DAY 10
7

情境

現今科技越來越進步,手機拿起來,隨時隨地都可以拍照,記錄下生活中美好的瞬間。

並且,我們一天到晚在瀏覽網站,我們將越來越少看間一個網站是完全沒有圖片的。因此,將照片放到網站上,是生活當中再平凡不過的一件事了。

特別是,我們今天去了什麼特別的地方,留下了一張網美照,就會有一股衝動很想換上新的大頭貼,藉此昭告天下我去哪個風景優美的地方到此一遊~


圖片來源:https://www.fiftyplus.com.tw/articles/21891

你能看見多遠的未來呢?

身為一個前端工程師,當我們想要把圖片放上網站上時,我們會怎麼做呢?

下面是一張出去玩的自拍照:

因為覺得很有紀念性,所以順勢就把他變成大頭貼了,現在很流行的大頭貼都是圓形,不管是 Line 帳號、Google 帳號、Facebook 帳號、IG 帳號的大頭貼,也都是圓形:

我們的程式碼可能就會這樣寫:

<Avatar>
  <img className="avatar__image" src="taiming.png" alt="" width="200" height="200" />
  <div className="avatar__name">Taiming</div>
</Avatar>
.avatar__image {
  box-shadow: 0px 2px 15px -1px rgb(0 0 0 / 20%), 0px 1px 2px 0px rgb(0 0 0 / 14%), 0px 1px 17px 0px rgb(0 0 0 / 12%);
  border-radius: 100%;
}

.avatar__name {
  text-align: center;
  margin-top: 12px;
  font-size: 24px;
  font-weight: 900;
  color: #5c5c5c;
}

到目前為止看起來都一切正常,除了我不是一位正妹,對大家比較抱歉之外 XD
但是在這正常的背後,其實我有做過一些小手腳才讓上面畫面看起來這麼正常。
這個小手腳就是,我提供的大頭貼照片是已經裁剪過的 1:1 比例的圖片。

但現實當中,除非你有特別設置過,否則,我們拍到的照片應該不太會是 1:1 的圖片。

例如這樣:

那我們把這個非 1:1 的照片,原封不動的狀況下,直接換掉上面 <img />src ,就會被非等比例的延展或壓縮,如下圖:

照片勢必會被壓縮的理由是因為,我們要的是一個圓形的照片,所以在 <img /> 上面的圖片長寬已經設置為 with="200"height="200" 了,把一張非 1:1 的照片放入 1:1 的容器當中,那勢必會有一些壓縮或延展。

那該怎麼辦呢?假設我們照片是 4:3 的比例,那我們是不是把 <img /> 的長寬也調整成 4:3 就能夠避免照片扭曲了?

既然如此,我們就來試試看吧:

<img className="avatar__image" src={url} alt="" width={200} height={120} />

結果:

果然事情沒有我們想的這麼單純,我們要的是圓形的照片,但這樣改了 <img /> 的長寬之後,雖然解決了圖片被壓縮或延展的問題,但我們照片就再也不是圓形了。

所以,此時如果覺得非常無助,就只好慢慢去把照片裁切成 1:1,之後再放上網站。

如果我們只處理一張照片,那這倒是小事,很多小工具可以幫我們完成。但如果我們一次要處理一批照片呢?100 張?500 張?

另外,如果我們是設計系統的人,要讓使用者上傳他的照片,那難不成我們要要求使用者在本機裁切好之後再上傳嗎?想必使用者一定會覺得我們網站很難用。

試試使用 object-fit 來調整元素內容吧

object-fit 是決定圖片填滿方式的屬性,用法與 background-size 相當類似,不過因為使用了 img tag,因此能夠保留原本的特性,另外也可以加上 alt 屬性來達到較好的 SEO。

屬性說明:

/* Keyword values */
object-fit: fill; /* 預設值,預設會強制變形至 css 所定義的元素寬高,不管原檔比例。 */
object-fit: contain; /* 增加或減少載入物件的寬度及高度(維持原比例)直到放得進所定義的元素寬高。 */
object-fit: cover; /* 填滿元素的寬度及高度(維持原比例),通常會剪掉部分的物件。 */
object-fit: none; /* 不做任何大小及比例調整。 */
object-fit: scale-down; /* 將會選擇設為 none 或 container 兩者間較小的那個物件。 */

因此,我們只要在 img 加上 object-fit: cover,就能夠剪掉超出範圍的部分,維持原本圖片的比例了:

.avatar__image {
  box-shadow: 0px 2px 15px -1px rgb(0 0 0 / 20%), 0px 1px 2px 0px rgb(0 0 0 / 14%), 0px 1px 17px 0px rgb(0 0 0 / 12%);
  border-radius: 100%;
  object-fit: cover; /* 防止圖片變形 */
}

另外,如果圖片被裁減之後,在圖片正中央並不是我們想要的主題,我們也能夠透過 object-position 來進行調整。

例如:

object-position: center top;
object-position: 100px 50px;

但是要特別注意 object-fit/object-position 不支援 IE,因為很難預期觀看者是否會使用 IE 來瀏覽你的網頁。不過,隨著微軟公布不再支援 IE,若系統可以不用考慮 IE,就能夠盡情使用這個屬性。

使用 background-image 屬性來呈現

除了使用 img tag 以外,我們也能夠使用 CSS 的 background-image 來呈現圖片:

.avatar__image {
  width: 200px;
  height: 200px;
  background-image: url('taiming.png');
  background-size: cover;
}
<div class="avatar__image"></div>

如上述程式碼所示,background-image 也支援許多屬性來調整圖片的呈現方式:

  • background-size
    • cover: 縮放背景圖片以完全覆蓋背景,可能圖片的部分會看不見。
    • contain: 圖片縮放以完全裝入背景區,可能背景部分會空白。
  • background-repeat
    • 主要用途是讓背景圖片可以重複拼接,當背景圖片小於容器時,能夠用重複拼貼的方式來填滿容器。
  • background-attachment
    • 背景圖片的位置是否要固定在 viewport(視圖)上,還是背景圖片會隨著它的 containing block(外層容器)一起滾動。
  • background-position
    • 主要用來設置圖片起始位置,默認情況下,圖片會放在容器的左上角。

CSS background-image 因為屬性比較多,所以能夠讓我們做一些更細微的設置。不過跟 img 比起來,他失去能能夠調校 SEO 的 alt 屬性,並且 img 會更符合 HTML 語意化標籤。

小結

在今天的內容中,我們舉了一個圖片比例容易會變形的情境,然後我們提出兩種解決的可能性:

  • img tag 上使用 object-fit 來調整元素內容
  • div tag 上使用 background-image 屬性來呈現

圖片變形的情境很可能會發生在圖片容器與圖片比例不相合的時候,特別是現代瀏覽網頁的裝置五花八門,使用者可能用各種不同尺寸的裝置在瀏覽網頁,因此在處理圖片的時候會需要考慮到這些可能性。在開發時可能在你的裝置上沒問題,但在不同尺寸的裝置上面可能就會明顯變形,這些部分會需要特別留意喔!

[聊天時間]
圖片的比例變形其實有時候只是一個微小的細節,甚至他也不會造成系統當掉。因此有些工程師並不會特別在意,甚至對這樣的錯誤嗤之以鼻,覺得這麼無聊的東西還叫我調整,調校效能的問題才更能顯現自己的專業。

不過事實上,當網頁發生圖片變形時,使用者體驗上會讓人覺得這是一個不專業的網站,專業水準上面會大大的扣分。

其實我們只需要多一點細心,多一點考慮,我們就能夠發現這樣的錯誤並且快速的修正。

另一方面,圖片比例變形對設計師而言其實是非常重大的缺失,所以在他們看來會非常在意,即使這對在美感方面沒有那麼在行的工程師看起來可能沒什麼。

我們在這方面如果也能夠做得好,不只是能夠提升自己和網站體驗的專業程度,也能夠跟合作的設計師擁有良好的合作關係,這對於要打造一個好的、專業的產品是很重要的環節。


上一篇
【Day09】內容長度 - 固定的寬度
下一篇
【Day11】圖片 - 被遺忘的背景重複問題
系列文
防禦性 CSS - 建立「防患未然」的匠人心態30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
阿Tu
iT邦新手 5 級 ‧ 2022-09-30 01:06:50

限制才300字,作者感覺寫了不止1300,用心給推!

Taiming iT邦研究生 5 級 ‧ 2022-09-30 07:50:38 檢舉

感謝您的用心閱讀!還幫我算字數!真是令我受寵若驚 XDD

我要留言

立即登入留言